#include "ParkinglotDB.h"

std::map<int, Car>::iterator ParkinglotDB::FindCar(int license_plate)
{
	if(!license_plate)
		return Car_list.end();
	it = Car_list.begin();  
	while (it != Car_list.end())
		if (it->second.license_plate == license_plate ) 
			return it;
		else it++;
		return Car_list.end(); 
}

std::map<int, Car>::iterator ParkinglotDB::FindIfEntered(int car_id)
{
	it = Car_list.begin();  
	while (it != Car_list.end())
		if ( it->second.car_id == car_id ) 
			return it;
		else it++;
		return Car_list.end(); 
}


void ParkinglotDB::InitLot()
{
	autoprint=true;
	TakenSlots=0; //assumption
	char line[256];
	SlotsNum=0;
	CarsNum=0; 
	CurrentCarsNum=0; 
	ifstream myfile1 ("parking.txt"); 
	ifstream myfile2 ("Eligible.txt");
	if (myfile1.is_open())
	{
		while (!myfile1.eof()) 
		{
			myfile1.getline(line,256);
			//getline (myfile,line);
			ParkingLot_list.insert(pair<int,ParkingLot>(SlotsNum,ParkingLot()));
			//This STRTOK thing has extremely strange syntex
			ParkingLot_list[SlotsNum].x1=atoi(strtok(line," ,"));
			ParkingLot_list[SlotsNum].y1=atoi(strtok(NULL," ,"));
			ParkingLot_list[SlotsNum].x2=atoi(strtok(NULL," ,"));
			ParkingLot_list[SlotsNum].y2=atoi(strtok(NULL," \n"));
			ParkingLot_list[SlotsNum].carLP=0; 
			ParkingLot_list[SlotsNum].NumEntered=0; 
			SlotsNum++;
		}
		myfile1.close();
	}
	if(myfile2.is_open())
	{
		int i=0; 
		while (!myfile2.eof()) 
		{
			myfile2.getline(line,256);
			//getline (myfile,line);
			Eligible_list.insert(pair<int,Car>(i,Car()));
			//This STRTOK thing has extremely strange syntex
			Eligible_list[i].license_plate=atoi(strtok(line," \n")); 
			i++; 
		}
		myfile2.close();
	}
	else cout << "Unable to open file"; 
	return;
} 
/*this will generate a new car in the parking lot*/
void ParkinglotDB::CarEntered(int car_id)
{
	Car_list.insert(pair<int,Car>(car_id,Car())); 
	Car_list[car_id].car_id = car_id; 
	time_t rawtime;
	time (&rawtime );
	Car_list[car_id].entry_time = rawtime;
	CarsNum++; 
	CurrentCarsNum++; 
}

/*this will delete a car from the parking lot*/
void ParkinglotDB::CarExits(int car_id)
{
	if(autoprint)
		cout << "\n>>>Car license plate number " << Car_list[car_id].license_plate <<" exits";
	Car_list[car_id].car_parking = -2;   
	CurrentCarsNum--; 
}

/*sets the license plate of an existing car, returns false if car_id is not in the database*/
bool ParkinglotDB::SetLicensePlate (int car_id, int license_plate)
{ 
	if ((license_plate < 0) || (Car_list[car_id].license_plate))
		return false; 
	it = FindCar(license_plate);
	if (it != Car_list.end())
	{
		it->second.times_in++; 
		it->second.car_parking = -1; 
		Car_list[car_id]=it->second;
		Car_list.erase(it->second.car_id); 
	}
	else
		Car_list[car_id].license_plate = license_plate; 
	if(autoprint)
		cout << "\n>>>Car license plate number " <<license_plate <<" entered";
	return true; 
}

/*sets the parking place of an existing car, returns false if car_id is not in the database */
/*bool ParkinglotDB::CarParked (int car_id, float x, float y)
{
	if(!Car_list[car_id].car_id)
		return false; //no such car, wtf you want ? 
	Lotit = ParkingLot_list.begin();
	while (Lotit != ParkingLot_list.end())
	{
		ParkingLot &p=Lotit->second;
		if(p.x1 < x && p.y1<y && p.x2>x && p.y2>y)
		{
			if(p.carID>=0)
				return false;//Parking is taken, vehicle manslaughter
			p.carLP=Car_list[car_id].license_plate;
			p.carID=car_id; 
			p.NumEntered++; 
			Car_list[car_id].car_parking=Lotit->first+1;
			if(autoprint)
				cout << "\n>>>Car license plate number " <<p.carLP <<" entered to parking number " << Car_list[car_id].car_parking;
			TakenSlots++;
			return true; 
		}
		Lotit++;
	}
	return false; //no such parking lot.
}*/

//The new car parked with roey's acceptance test !!!
bool ParkinglotDB::CarParked (int car_id, float x, float y)
{
	string s1; 
    //if(!Car_list[car_id].car_id)
    //    return false; //no such car, wtf you want ? 
    Lotit = ParkingLot_list.begin();
    while (Lotit != ParkingLot_list.end()) 
    {
        ParkingLot &p=Lotit->second;
        if(p.x1 < x && p.y1<y && p.x2>x && p.y2>y)
        {
            if(p.carID>=0)
                return false;//Parking is taken, vehicle manslaughter \
				ofstream file;
			ofstream file;
			file.open("Test.txt",std::ios::app);
			streambuf* sbuf = cout.rdbuf();
			cout.rdbuf(file.rdbuf());
            p.carLP=Car_list[car_id].license_plate;
            p.carID=car_id; 
            p.NumEntered++; 
            Car_list[car_id].car_parking=Lotit->first+1;
            TakenSlots++;
			cout << "\n		 -Parking Output-		\n"; 
			cout << "\n>>>There are " << TakenSlots << " Parking Spaces occupied\n"; 
			cout << "\n>>>There are " << CarsNum <<" cars in the parking lot\n"; 
			PrintOccupiedSpots(s1); 
			cout << s1; 
			cout.rdbuf(sbuf);
			file.close();
			if(autoprint)
				cout << "\n>>>Car license plate number " <<p.carLP <<" entered to parking number " << Car_list[car_id].car_parking;
            return true; 
        }
        Lotit++;
    }
    return false; //no such parking lot. 
} 

/*returns the car_id of the car in the parking place of (x,y), 
and updating the database accordingly*/

//I DON'T KNOW WHO CHANGED THIS , BUT IT'S NOT ME !!!
int ParkinglotDB::CarUnparked(int x, int y)
{
	Lotit = ParkingLot_list.begin();  
	while (Lotit != ParkingLot_list.end())
	{
		ParkingLot &p=Lotit->second;
		if(p.x1 < x && p.y1<y && p.x2>x && p.y2>y)
		{
			int rval=p.carID;
			int clp=Lotit->second.carLP;
			//it=FindCar(p.carLP);
			if(p.carID ==-1)
				return -1; //parking is empty WTF!!!
			Car_list[Lotit->second.carID].car_parking=-1;
			Lotit->second.carLP=0;
			Lotit->second.carID=-1;
			if(autoprint)
				cout << "\n>>>Car license plate number " <<clp <<" unparked";
			return rval;
		}
		Lotit++;
	}
	TakenSlots--; 
	return 0;//No such parking exists
}


string ParkinglotDB::getCarVideo(int car_id){
	std::map<int, Car>::iterator it = FindCar(car_id);
	if( it == Car_list.end() ) return "";
	return (*it).second.getVideoLocation();
}

/*returns some description of the car location*/ 
int ParkinglotDB::WhereIsMyCar(int license_plate, string &s)
{
	std::map<int, Car>::iterator it = FindCar(license_plate); 
	if ((it == Car_list.end()) || (it->second.car_parking == -2) )
	{
		s="Car Not exists";
		return -2;
	}
	else
	{
		if(it->second.car_parking!=-1)
		{
			std::stringstream ss;
			ss << it->second.car_parking;
			ss >> s;
			s="Car is parking in parking number "+s;
		}
		else
			s="Car is currently looking for parking";
		return it->second.car_parking;
	}
}


/*prints the occupied parking places*/ 
/*
void ParkinglotDB::PrintOccupiedSpots(string &s)
{
	std::stringstream ss;

	Lotit = ParkingLot_list.begin();  
	int i=1;
	while (Lotit != ParkingLot_list.end())
	{
		if(Lotit->second.carLP)
		{
			ss <<"Car: " << Lotit->second.carLP << ", Is parking in : " << i;
			ss << "\n";
		}
		Lotit++;
		i++;
	}
	ss.getline(tmpc,300,'\0');
	s=tmpc;
	return;
}
*/

//New function with roey's acceptance test modifications
void ParkinglotDB::PrintOccupiedSpots(string &s)
{
	std::stringstream ss;

	Lotit = ParkingLot_list.begin();  
	int i=1;
	while (Lotit != ParkingLot_list.end())
	{
		if(Lotit->second.carLP)
		{
			cout << "\n>>>Car license plate number " << Lotit->second.carLP <<" is in parking number " << i << "\n"; 
		}
		Lotit++;
		i++;
	}
	ss.getline(tmpc,300,'\0');
	s=tmpc;
	return;
}
/* prints log to TXT file the describes for every parking is it empty or who parking there, 
and when he entered to the parking lot*/
void ParkinglotDB::PrintLogToFile()
{

	ofstream file;
	file.open ("Log.txt");
	streambuf* sbuf = cout.rdbuf();
	cout.rdbuf(file.rdbuf());
	cout << "					     LOG \n";
	it = Car_list.begin();  
	while (it != Car_list.end())
	{
		if ( it->second.car_id != -2) 
		{
			cout <<"Car: " << it->second.license_plate;
			cout <<" , is in parking number :" << it->second.car_parking;
			cout <<", Entered in: " << ctime(&(it++->second.entry_time));
			cout << "\n";
		}
	}
	cout.rdbuf(sbuf);
	file.close();
	return;
}

int ParkinglotDB::IsParkingAvailble(int parking_id, string &s)
{
	std::stringstream ss;
	if(ParkingLot_list[parking_id].carID>=0)
	{
		ss << "Parking taken by car number: " << ParkingLot_list[parking_id].carLP ;
		ss.getline(tmpc,300,'\0');
		s=tmpc;
		return ParkingLot_list[parking_id].carLP;
	}
	ss<< "Parking is availble";
	ss.getline(tmpc,300,'\0');
	s=tmpc;
	return -1;
}

bool ParkinglotDB::isThisParkingSlot(int x, int y)
{
	Lotit = ParkingLot_list.begin();  
	while (Lotit != ParkingLot_list.end())
	{
		ParkingLot &p=Lotit->second;
		if(p.x1 < x && p.y1<y && p.x2>x && p.y2>y)
			return true;
		Lotit++;
	}
	return false; //no such parking lot.
}
void ParkinglotDB::AutoPrint()
{
	autoprint=!autoprint;
	return;
}

int ParkinglotDB::HowManySlotsFree(string &s)
{
	std::stringstream ss;
	ss << "There are " << (SlotsNum-TakenSlots) << " Free Slots In The Parking Lot" ;
	ss.getline(tmpc,300,'\0');
	s=tmpc;
	return (SlotsNum-TakenSlots); 
}

void ParkinglotDB::HowLongCarIn(int license_plate, string &s)	
{
	std::stringstream ss;
	it = FindCar(license_plate);
	if ((it == Car_list.end()) || (it->second.car_parking == -2) )
		ss << "Car Is Not Here"; 
	else
	{
		time_t rawtime; 
		double seconds; 
		seconds = difftime( time(&rawtime) , (FindCar(license_plate))->second.entry_time); 
		ss << "The Car Has Been Here For" << seconds << " Seconds";
	}
	ss.getline(tmpc,300,'\0');
	s=tmpc;
} 

/*check this!!!!*/
void ParkinglotDB::TheMostWantedSlot(string &s)						
{
	std::stringstream ss;
	Lotit = ParkingLot_list.begin();  
	int wanted=0; 
	int i=0; 
	while (Lotit != ParkingLot_list.end())
	{
		if(Lotit->second.NumEntered > wanted)
		{
			wanted=Lotit->second.NumEntered; 
		}
		Lotit++;
	}

	Lotit = ParkingLot_list.begin();
	while (Lotit != ParkingLot_list.end())
	{
		if(Lotit->second.NumEntered == wanted)
		{
			if (i)
				ss << "Moreover, "; 
			ss <<"Parking Slot: " << Lotit->first << " Is The Most Wanted"; 
			i++; 
		}
		Lotit++;
	}
	ss.getline(tmpc,300,'\0');
	s=tmpc;
} 

void ParkinglotDB::HowManyEntered(string &s)
{
	std::stringstream ss;
	ss << "The Number Of Cars That Entered To The Lot Today Is: " << CarsNum; 
	ss.getline(tmpc,300,'\0');
	s=tmpc;
} 

void ParkinglotDB::WhenEntered(int license_plate, string &s)			
{
	std::stringstream ss;
	it = FindCar(license_plate);
	if ((it == Car_list.end()) || (it->second.car_parking == -2) )
		ss << "Car Is Not Here"; 
	else
		ss << "The Car Entered In: " <<ctime ( &(it->second.entry_time)) << ""; 
	ss.getline(tmpc,300,'\0');
	s=tmpc;
} 

void ParkinglotDB::NumOfTimes(int license_plate, string &s)
{
	std::stringstream ss;
	it = FindCar(license_plate);
	if ( (it == Car_list.end()) || (it->second.car_parking == -2) )
		ss << "Car Is Not Here"; 
	else
		ss << "The Car Has Been Here " << it->second.times_in << " times"; 
	ss.getline(tmpc,300,'\0');
	if(tmpc[strlen(tmpc)-1] == '\n') tmpc[strlen(tmpc)-1] = '\0';
	s=tmpc;
}

bool ParkinglotDB::IsEligible(int license_plate, string &s)
{
	std::stringstream ss;
	it = Eligible_list.begin();  
	while ((it != Eligible_list.end()) && (it->second.license_plate != license_plate ))
		it++; 
	if (it == Eligible_list.end()) 
	{
		ss << "The Car Is Not Eligible"; 
		ss.getline(tmpc,300,'\0');
		s=tmpc;
		return false; 
	}
	else
	{
		ss << "The Car Is Eligible"; 
		ss.getline(tmpc,300,'\0');
		s=tmpc;
		return true; 
	}	
}

int ParkinglotDB::GimmieNumOfTimes(int license_plate)
{
	it = FindCar(license_plate);
	if (it == Car_list.end())
		return 0; 
	else
		return it->second.times_in; 
}

int ParkinglotDB::GetLocation(int license_plate)
{
	it = FindCar(license_plate);
	if( it == Car_list.end() ) return -2;
	return it->second.car_parking; 
}

int ParkinglotDB::HowManySlotsTaken(string &s)
{
	std::stringstream ss;
	ss << "There are " << TakenSlots << " Free Slots In The Parking Lot" ;
	ss.getline(tmpc,300,'\0');
	s=tmpc;
	return TakenSlots; 
}


void ParkinglotDB::addVideo( int carId, string video){
	it = Car_list.find(carId);
	if( it == Car_list.end() ) return;
	it->second.videoLocataion = video;
	return;
}